<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>理解1</title>
</head>
<body>
<script>

  /*
  * 函数传递数据的方式不只限于方法参数 还可以通过this传值，只不过this传值是隐式传递
  * 可以在函数内部通过this.获取到传递而来的值 只是由于调用的不同 this可能会传递不同的值
  * 所以我们在普通函数(区别于构造函数)中使用this时一定要去思考此时的this是什么
  *
  * */
  function foo(a, b) {
    /*这里其实是传递了三个值*/
    console.log(a, b, this.age);
  }

  foo.call({ age: 12 }, 1, 2);


  /*
  * 如果一个函数的逻辑是接收一个对象并进行修改,最后将修改后的对象进行返回
  * 但要求是一个纯函数,即返回的对象是一个新的对象，而不是原对象
  * */



  /*
  *
  * 思路1:在函数内部直接创建一个新的对象
  * 如果是直接创建的话那么这个新对象无法沿用之前对象的属性和方法
  * */
  function fee1(attr,fn) {
    let obj = {}
  /*这里传入的attr是字符串所以要使用[]取属性*/
    obj[attr] =fn(this[attr])
    return obj

  }

/*
*
* 如果不用考虑新对象的话可以将原对象或者直接将this传递
* */
  function fee2(obj, attr, fn) {
    obj[attr] =fn(obj[attr])
    return obj
  }


  /*
  * 一个最万能的方法是将原对象上的一切都复制给新对象
  *
  * */
  function fee3(attr, fn) {
    let newThis = Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this))

    newThis[attr] =fn(this[attr])
    return obj
  }



  let obj = {
    age: 23,
    tell(){
      console.log('tell');
    }
  };

 let obj1 =  fee2(obj, "age", attr => attr + 1);
  console.log(obj1);

let obj2 =  fee1.call(obj, "age", attr => attr + 1)
  console.log(obj2.age);


  let obj3 =  fee3( "age", attr => attr + 1);
  console.log(obj3);

  console.log();

  class User{
    constructor() {
      this.a = 1
      this.b = 2
    }
    sum(){
      return this.a + this.b
    }

    alter(attr,f){
      let newUser = new this.constructor()
      newUser[attr] = f(this[attr])
    }
  }


</script>
</body>
</html>